﻿
#ifndef ModelMesh_h
#define ModelMesh_h

#include <CSharpPropertyMethods.h>

#include <System/Collections/Generic/RList.h>

#include <Riccsson/Xna/Framework/Graphics/ModelMeshPartCollection.h>

namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			namespace Graphics
			{
				// Summary:
				//     Represents a mesh that is part of a Model.
				class ModelMesh sealed
				{
					private: GC_PTR<GraphicsDevice> graphicsDevice;
					private: Riccsson::System::Collections::Generic::List<GC_PTR<ModelMeshPart>> parts;

					public: ModelMesh(GraphicsDevice* graphicsDevice, Riccsson::System::Collections::Generic::List<GC_PTR<ModelMeshPart>> parts)
					{
						// TODO: Complete member initialization
						this->parts = parts;
						this->graphicsDevice = graphicsDevice;
			
						MeshParts = new ModelMeshPartCollection(parts);
			
						for (int i = 0; i < parts->Count; i++) {
							parts[i].parent = this;
						}
			
						Effects = new ModelEffectCollection();
					}
		
					/*internal void BuildEffectList()
					{
						List<Effect> effects = new List<Effect>();
						foreach (ModelMeshPart item in parts) 
						{
							if (!effects.Contains(item.Effect))
							{
								if (item.Effect != null)
									effects.Add(item.Effect);
							}
						}
						Effects = new ModelEffectCollection(effects);
					}*/
		
					// Summary:
					//     Gets the BoundingSphere that contains this mesh.
					public: PROP3_GET(BoundingSphere, boundingSphere)
					{
						throw;
					}
					public: PROP3_SET(BoundingSphere, boundingSphere)
					{
						throw;
					}

					//
					// Summary:
					//     Gets a collection of effects associated with this mesh.
					public: PROP3_GET(GC_PTR<ModelEffectCollection>, Effects)
					{
						throw;
					}
					public: PROP3_SET(GC_PTR<ModelEffectCollection>, Effects)
					{
						throw;
					}

					//
					// Summary:
					//     Gets the ModelMeshPart objects that make up this mesh. Each part of a mesh
					//     is composed of a set of primitives that share the same material.
					public: PROP3_GET(GC_PTR<ModelMeshPartCollection>, MeshParts)
					{
						throw;
					}
					public: PROP3_SET(GC_PTR<ModelMeshPartCollection>, MeshParts)
					{
						throw;
					}

					//
					// Summary:
					//     Gets the name of this mesh.
					public: GC_PTR<Riccsson::System::string> Name>
					//
					// Summary:
					//     Gets the parent bone for this mesh. The parent bone of a mesh contains a
					//     transformation matrix that describes how the mesh is located relative to
					//     any parent meshes in a model.
					public: GC_PTR<ModelBone> ParentBone;
					//
					// Summary:
					//     Gets or sets an object identifying this mesh.
					public: GC_PTR<Riccsson::System::object> Tag;
				
					// Summary:
					//     Draws all of the ModelMeshPart objects in this mesh, using their current
					//     Effect settings.
					public: void Draw()
					{	
						for(int i = 0; i < MeshParts->Count; i++)
						{
							var part = MeshParts[i];
							var effect = part.Effect;
				
							if (part.PrimitiveCount > 0)
							{
								this->graphicsDevice.SetVertexBuffer(part.VertexBuffer);
								this->graphicsDevice.Indices = part.IndexBuffer;
                    
								for (int j = 0; j < effect.CurrentTechnique.Passes.Count; j++)
								{
									effect.CurrentTechnique.Passes[j].Apply ();
									this->graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, 0, part.NumVertices, part.StartIndex, part.PrimitiveCount);
								}
							}
						}
					}
				};
			}
		}
	}
}

#endif
